#ifndef TASK_CHAIN_H
#define TASK_CHAIN_H

#include <functional>
#include "../global.h"
#include "task_define.h"
#include "scheduler/sequence_scheduler.h"
#include "scheduler/fallback_scheduler.h"
#include "scheduler/parallel_scheduler.h"
#include "utils/thread/runnable.h"
#include "task/context.h"

namespace task
{

using TaskChainFinishCallback = std::function<void(const std::string &, const Context *)>;
using TaskChainStartCallback = std::function<void(const std::string &, const Context *)>;

/**
 * @brief:  任务链，一个任务链内部包含一个任务调度器
 *          只有从任务链开始任务，才可以使用上下文数据传递
 * @author: sherlock_lht
 */
class TaskChainData;
class TaskChain: public base::Runnable
{
public:
    explicit TaskChain(const std::string &name, const scheduler::AbstractSchedulerConstPtr &scheduler);
    explicit TaskChain(const std::string &name);
    ~TaskChain() override;

    /**
     * @brief:  获取任务链名称
     * @author: haitao.lin
     */
    std::string getName() const;

    /**
     * @brief:  获取任务当前状态
     * @author: sherlock_lht
     */
    TaskChainStatus getTaskStatus() const;

    /**
     * @brief:  设置任务链执行结束时的回调，任务链没有开始，也会执行
     * @author: sherlock_lht
     */
    void setFinishCallback(TaskChainFinishCallback callback);

    /**
     * @brief:  设置任务链执行前得回调
     * @author: lianpu.sun
     */
    void setStartCallback(TaskChainStartCallback callback);

    /**
     * @brief:  设置调度器
     * @author: sherlock_lht
     */
    void setScheduler(const scheduler::AbstractSchedulerConstPtr &scheduler);

    /**
     * @brief:  保存任务链中的上下文数据，其中的子任务都可以获取到
     * @author: sherlock_lht
     */
    template<class T>
    void setData(const std::string &name, const T &value)
    {
        std::any data = value;
        setData(name, data);
    }

    /**
     * @brief:  获取任务链中的上下文数据
     * @author: sherlock_lht
     */
    template<class T>
    bool getData(const std::string &name, T &value)
    {
        return getData(name, value);
    }

    /**
     * @brief:  开始运行整个任务链
     * @author: sherlock_lht
     */
    virtual void start();

    /**
     * @brief:  暂停任务
     * @author: sherlock_lht
     */
    virtual void pause();

    /**
     * @brief:  重新开始任务
     * @author: sherlock_lht
     */
    virtual void resume();

    /**
     * @brief:  取消任务
     * @author: sherlock_lht
     */
    virtual void cancel();

    /**
     * @brief:  执行任务链结束的回调函数
     * @author: sherlock_lht
     */
    void execFinishCallback();

    void setTaskEventNotify(task::TaskChainEventNotify event_notify);

private:
    void run() override;

    /**
     * @brief:  保存任务链中的上下文数据
     * @author: sherlock_lht
     */
    void setData(const std::string &name, std::any &value);

    /**
     * @brief:  获取任务链中的上下文数据
     * @author: sherlock_lht
     */
    bool getData(const std::string &name, std::any &value);

    /**
     * @brief:  设置任务链的状态
     * @author: sherlock_lht
     */
    void setTaskChainStatus(TaskChainStatus task_chain_status);

    void taskEventNotify(task::TaskEventType task_event_type);

private:
    DECLARE_DATA(TaskChain)
};
}

#endif //TASK_CHAIN_H
